#include "iConfig.hpp"

#if GLF_VIRTUAL_FILESTREAM

#include <glf/io/fileStreamMgr.h>
#include <algorithm>

namespace glf {

FileStreamMgr::FileStreamMgr()
	: mCounter(0)
{
}

FileStreamMgr::~FileStreamMgr()
{
	GLF_ASSERT(mActiveList.size()   == 0);
	GLF_ASSERT(mInactiveList.size() == 0);
}

bool FileStreamMgr::Open(FileStream* fileStream, const char* filename, ios::openflag flag)
{
	bool success = fileStream->OpenImpl(filename, flag);

	if(success)
	{
		Insert(fileStream);
		
		fileStream->Check();
	}

	return success;
}

void FileStreamMgr::Close(FileStream* fileStream)
{
	std::vector<FileStream*>::iterator fs;
	
	LockScope lock(mMutex);

	fs = std::find(mActiveList.begin(), mActiveList.end(), fileStream);
	if(fs != mActiveList.end())
	{
		mActiveList.erase(fs);
		fileStream->CloseImpl();
		return;
	}

	fs = std::find(mInactiveList.begin(), mInactiveList.end(), fileStream);
	if(fs != mInactiveList.end())
	{
		mInactiveList.erase(fs);
		return;
	}
}

void FileStreamMgr::Ensure(FileStream* fileStream)
{
	{
		LockScope lock(mMutex);

		if(fileStream->mStatus == FileStream::STATUS_OUT)
		{
			mInactiveList.erase(std::find(mInactiveList.begin(), mInactiveList.end(), fileStream));
			Insert(fileStream);
			
			fileStream->FileIn();
			
			printf("A: %d, I: %d\n", mActiveList.size(), mInactiveList.size());
		}
	}
	
	fileStream->Check();
}

void FileStreamMgr::FileOutAllFiles()
{
	LockScope lock(mMutex);

	for(std::vector<FileStream*>::iterator i = mActiveList.begin(), end = mActiveList.end(); i != end; ++i)
	{
		(*i)->FileOut();
		mInactiveList.push_back(*i);
	}

	mActiveList.clear();
}

void FileStreamMgr::Insert(FileStream* fileStream)
{
	LockScope lock(mMutex);

	if(mActiveList.size() < MAX_FILESTREAM)
	{
		mActiveList.push_back(fileStream);
	}
	else
	{
		static CounterComparator comaparator;
		std::sort(mActiveList.begin(), mActiveList.end(), comaparator);

		FileStream* inactiveFileStream = mActiveList.back();
		mActiveList.pop_back();

		inactiveFileStream->FileOut();

		mActiveList.push_back(fileStream);
		mInactiveList.push_back(inactiveFileStream);
	}
}

uint64 FileStreamMgr::IncrCounter()
{
	return mCounter++;
}

} // end namespace glf

#endif // GLF_VIRTUAL_FILESTREAM
